<?php
/**
 * 生成验证码类，根据初始化参数构造验证码对象，提高获取验证码值和显示验证码两个函数
 *
 * 基于(cool-php-captcha-0.3 http://code.google.com/p/cool-php-captcha/)
 * 16:46 2010-09-17
 */

class pf_captcha
{

	public $im;
	public $captcha_value; //验证码值
	public $width  = 150;
	public $height = 60;
	public $min_word_length = 4;
	public $max_word_length = 4;
	public $background_color = array(100, 255, 255);
	public $blur = true; //字体边缘轮廓
	public $image_format = 'jpeg'; // 图片类型
	public $max_rotation = 5; //旋转设置 顺时针
	public $resources_path = 'resources'; //字体路径
	public $text_color; // 验证码颜色
	public $colors = array(
		array(27,78,181), // blue
		array(22,163,35), // green
		array(214,36,7),  // red
	);

	/**
	 * 字体配置
	 *
	 * - font: TTF file
	 * - spacing: 字符间距
	 * - minSize: 最小字体
	 * - maxSize: 最大字体
	 */
	public $fonts = array(
		'Antykwa'  => array('spacing' => -3, 'minSize' => 27, 'maxSize' => 30, 'font' => 'AntykwaBold.ttf'),
		'Candice'  => array('spacing' =>-1.5,'minSize' => 28, 'maxSize' => 31, 'font' => 'Candice.ttf'),
		'DingDong' => array('spacing' => -2, 'minSize' => 24, 'maxSize' => 30, 'font' => 'Ding-DongDaddyO.ttf'),
		'Duality'  => array('spacing' => -2, 'minSize' => 30, 'maxSize' => 38, 'font' => 'Duality.ttf'),
		'Heineken' => array('spacing' => -2, 'minSize' => 24, 'maxSize' => 34, 'font' => 'Heineken.ttf'),
		'Jura'	 => array('spacing' => -2, 'minSize' => 28, 'maxSize' => 32, 'font' => 'Jura.ttf'),
		'StayPuft' => array('spacing' =>-1.5,'minSize' => 28, 'maxSize' => 32, 'font' => 'StayPuft.ttf'),
		'Times'	=> array('spacing' => -2, 'minSize' => 28, 'maxSize' => 34, 'font' => 'TimesNewRomanBold.ttf'),
		'VeraSans' => array('spacing' => -1, 'minSize' => 20, 'maxSize' => 28, 'font' => 'VeraSansBold.ttf'),
	);

	/** 波浪字体设置 */
	public $y_period	= 6;
	public $y_amplitude = 7;
	public $x_period	= 6;
	public $x_amplitude = 3;


	/**
	 * 图片质量
	 * 1: 低, 2: 中, 3: 高
	 */
	public $scale = 3;

	public function __construct($width = 150, $height = 60, $min_length = 4, $max_length = 6, $bg_color = NULL) {
		$this->width = $width;
		$this->height = $height;
		$this->min_word_length = $min_length;
		$this->max_word_length = $max_length;
		if (is_array($bg_color) && count($bg_color) == 3)
		{
			$this->background_color = $bg_color;
		}
		//生成随机字符
		$this->captcha_value = $this->get_captcha_text();
	}

	/**
	 * 返回生产的验证码的值 失败返回false
	 *
	 * @return string
	 */
	public function get_captcha_value()
	{
		return $this->captcha_value;
	}

	/**
	 * 输出显示验证码
	 *
	 */
	public function output()
	{
		$ini = microtime(true);

		$this->init_image(); //初始化图片

		$fontcfg = $this->fonts[array_rand($this->fonts)]; //随机字体
		$this->write_image_text($this->captcha_value, $fontcfg);

		$this->wave_image(); //字体波浪化
		if ($this->blur && function_exists('imagefilter'))
		{
			imagefilter($this->im, IMG_FILTER_GAUSSIAN_BLUR);
		}
		$this->resize_image(); //缩放图片

		$this->output_image();
		$this->cleanup();
	}

	/**
	 * 初始化图片资源
	 */
	protected function init_image() {
		// cleanup
		if (!empty($this->im))
		{
			imagedestroy($this->im);
		}

		$this->im = imagecreatetruecolor($this->width * $this->scale, $this->height * $this->scale);

		// 设置背景
		$bg_color = imagecolorallocate($this->im,
			$this->background_color[0],
			$this->background_color[1],
			$this->background_color[2]
		);
		imagefilledrectangle($this->im, 0, 0, $this->width * $this->scale, $this->height * $this->scale, $bg_color);

		//设置字体颜色
		$color = $this->colors[mt_rand(0, sizeof($this->colors)-1)];
		$this->text_color = imagecolorallocate($this->im, $color[0], $color[1], $color[2]);
	}

	/**
	 * 生成随机字符
	 *
	 * @return string Text
	 */
	protected function get_captcha_text($length = null) {
		if (empty($length))
		{
			$length = rand($this->min_word_length, $this->max_word_length);
		}

		$words = "abcdefghijlmnopqrstvwyz";
		$vocals = "aeiou";

		$text  = "";
		$vocal = rand(0, 1);
		for ($i=0; $i<$length; $i++)
		{
			if ($vocal)
			{
				$text .= substr($vocals, mt_rand(0, 4), 1);
			}
			else
			{
				$text .= substr($words, mt_rand(0, 22), 1);
			}
			$vocal = !$vocal;
		}
		return $text;
	}

	/**
	 * 生成字符图片
	 */
	protected function write_image_text($text, $fontcfg = array()) {
		if (empty($fontcfg))
		{
			$fontcfg  = $this->fonts[array_rand($this->fonts)];
		}

		// 字符路径
		$fontfile = $this->resources_path . '/fonts/' . $fontcfg['font'];

		/** Increase font-size for shortest words: 9% for each glyp missing */
		$lettersMissing = $this->max_word_length - strlen($text);
		$fontSizefactor = 1 + ($lettersMissing * 0.09);

		// 逐个生成图片字符
		$x	  = 20 * $this->scale;
		$y	  = round(($this->height * 27 / 40) * $this->scale);
		$length = strlen($text);
		for ($i = 0; $i < $length; $i++)
		{
			$degree   = rand($this->max_rotation * -1, $this->max_rotation);
			$fontsize = rand($fontcfg['minSize'], $fontcfg['maxSize']) * $this->scale * $fontSizefactor;
			$letter   = substr($text, $i, 1);

			$coords = imagettftext($this->im, $fontsize, $degree,
				$x, $y,
				$this->text_color, $fontfile, $letter
			);
			$x += ($coords[2] - $x) + ($fontcfg['spacing'] * $this->scale);
		}
	}

	/**
	 * 字符设置波浪
	 */
	protected function wave_image() {
		// X-坐标 
		$xp = $this->scale * $this->x_period * rand(1,3);
		$k = rand(0, 100);
		for ($i = 0; $i < ($this->width * $this->scale); $i++)
		{
			imagecopy($this->im, $this->im,
				$i-1, sin($k + $i / $xp) * ($this->scale * $this->x_amplitude),
				$i, 0, 1, $this->height * $this->scale
			);
		}

		// Y-坐标
		$k = rand(0, 100);
		$yp = $this->scale * $this->y_period * rand(1,2);
		for ($i = 0; $i < ($this->height * $this->scale); $i++)
		{
			imagecopy($this->im, $this->im,
				sin($k + $i / $yp) * ($this->scale * $this->y_amplitude), $i - 1,
				0, $i, $this->width * $this->scale, 1
			);
		}
	}

	/**
	 * 设置图片大小到设定值
	 */
	protected function resize_image() {
		$im_resize = imagecreatetruecolor($this->width, $this->height);
		imagecopyresampled($im_resize, $this->im,
			0, 0, 0, 0,
			$this->width, $this->height,
			$this->width*$this->scale, $this->height*$this->scale
		);
		imagedestroy($this->im);
		$this->im = $im_resize;
	}

	/**
	 * 显示图片
	 */
	protected function output_image() {
		if ($this->image_format == 'png' && function_exists('imagepng'))
		{
			header("Content-type: image/png");
			imagepng($this->im);
		}
		else
		{
			header("Content-type: image/jpeg");
			imagejpeg($this->im, null, 80);
		}
	}

	/**
	 * 清理图片资源
	 */
	protected function cleanup() {
		imagedestroy($this->im);
	}
}

?>
